//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.IO;
using System.Security;
using System.Text;
using System.Net;
using System.Web;
using CommunityServer.Configuration;

namespace CommunityServer.Components
{
	public class CSRequest 
	{
		private const int defaultTimeout_ = 60000;
		private static string referer_ = "Community Server";

		// Public so proxy classes can use this (i.e. Pings, Trackbacks, etc.)
		public static readonly string UserAgent = String.Format("Community Server {0} ({1}; .NET CLR {2};)", SiteStatistics.CommunityServerVersion, Environment.OSVersion.ToString(), Environment.Version.ToString());

        /// <summary>
        /// Creates a new HttpRequest with the default Referral value
        /// </summary>
		public static HttpWebRequest CreateRequest(string url) 
		{
			return CreateRequest(url,referer_);
		}

		/// <summary>
		/// Creates a new HttpRequest and sets the referral value.
		/// </summary>
		public static HttpWebRequest CreateRequest(string url, string referral) 
		{
		    ICredentials credentials = null;
		    
		    //note this code will not work if there is an @ or : in the username or password
            if (url.IndexOf('@') > 0)
            {
                string[] urlparts = url.Split('@');
                if (urlparts.Length >= 2)
                {
                    string[] userparts = urlparts[0].Split(':');

                    if (userparts.Length == 3)
                    {
                        string protocol = userparts[0];
                        string username = userparts[1].TrimStart('/');
                        string password = userparts[2];

                        credentials = new NetworkCredential(username, password);
                        url = url.Replace(string.Format("{0}:{1}@",username, password),"");
                    }

                }
            }
            else
            {
                credentials = CredentialCache.DefaultCredentials;
            }

			WebRequest req;
			
			// This may throw a SecurityException if under medium trust... should set it to null so it will return instead of error out.
			try { req = WebRequest.Create(url); }
			catch (SecurityException) { req = null; }
			
			HttpWebRequest wreq = req as HttpWebRequest;
			if (null != wreq) 
			{
				wreq.UserAgent = UserAgent;
				wreq.Referer =  referral;
				wreq.Timeout = defaultTimeout_;

			    if(credentials != null)
                    wreq.Credentials = credentials;

			    CSConfiguration config = CSConfiguration.GetConfig();
				if (config.ProxyHost != string.Empty)
				{
					WebProxy proxy = new WebProxy(config.ProxyHost, config.ProxyPort);

					if (config.ProxyBypassList != string.Empty)
						proxy.BypassList = config.ProxyBypassList.Split(',');
					proxy.BypassProxyOnLocal = config.ProxyBypassOnLocal;

					if (config.ProxyUsername != string.Empty)
						proxy.Credentials = new NetworkCredential(config.ProxyUsername, config.ProxyPassword);

					wreq.Proxy = proxy;
				}
			}
			return wreq;
		}

        public static  HttpWebResponse MakeHttpPost(string url, string referral, params HttpPostItem[] items)
        {
            return MakeHttpPost(CreateRequest(url,referral), items);
        }

        public static  HttpWebResponse MakeHttpPost(string url, params HttpPostItem[] items)
        {
            return MakeHttpPost(url,null,items);
        }
	
        public static HttpWebResponse MakeHttpPost(HttpWebRequest wreq, params HttpPostItem[] items)
        {
            if(wreq == null)
                throw new Exception("HttpWebRequest is not initialized");

            if(items == null || items.Length == 0)
                throw new Exception("No HttpPostItems");

            StringBuilder parameters = new StringBuilder();
            
            foreach(HttpPostItem item in items)
            {
                parameters.Append("&" + item.ToString());
            }

            byte[] payload = Encoding.UTF8.GetBytes(parameters.ToString().Substring(1));


            wreq.Method = "POST";
            wreq.ContentLength = payload.Length;
            wreq.ContentType = "application/x-www-form-urlencoded";
            wreq.KeepAlive = false;
			
            using(Stream st = wreq.GetRequestStream())
            {
                st.Write(payload, 0, payload.Length);
                st.Close();
				
             
                return  wreq.GetResponse() as HttpWebResponse;
            }

        }

        /// <summary>
        /// Gets the HttpResponse using the default referral
        /// </summary>
		public static HttpWebResponse GetResponse(string url)
		{
			return GetResponse(url,referer_);
		}

        /// <summary>
        /// Gets the HttpResponse using the supplied referral
        /// </summary>
		public static HttpWebResponse GetResponse(string url, string referral)
		{
			HttpWebRequest request = CreateRequest(url,referral);
			return (HttpWebResponse)request.GetResponse() ;
		}		

        /// <summary>
        /// Gets the full text at the url parameter
        /// </summary>
		public static string GetPageText(string url)
		{
			return GetPageText(url,referer_);
		}

        /// <summary>
        /// Gets the full text at the url parameter
        /// </summary>
		public static string GetPageText(string url, string referral)
		{
			HttpWebResponse response = GetResponse(url,referral);
			return GetPageText(response);
		}
		
		/// <summary>
		/// Gets the full text at the url parameter
		/// </summary>
		public static string GetPageText(HttpWebResponse response)
		{
			using (Stream s = response.GetResponseStream())
			{
				string enc = response.ContentEncoding.Trim() ;
				if ( enc == "" )
					enc = "us-ascii" ;
				Encoding encode = System.Text.Encoding.GetEncoding(enc);
				using ( StreamReader sr = new StreamReader( s, encode ) )
				{
					return sr.ReadToEnd() ;
				}
			}
		}

	}

    public class HttpPostItem
    {
        private string _parameter = null;
        private string _value = null;
        private bool _isEncoded = false;

        public HttpPostItem(string paramter, string postValue, bool isEncoded)
        {
            _parameter = paramter;
            _value = postValue;
            _isEncoded = isEncoded;
        }

        public HttpPostItem(string paramter, string postValue):this(paramter,postValue,false)
        {
            
        }

        public override string ToString()
        {
            return string.Format("{0}={1}", _parameter, _isEncoded ? _value : Globals.UrlDecode(_value));
        }
    }
}

